#version 300 es
precision mediump float;

#define float2 vec2
#define float3 vec3
#define float4 vec4
#define float3x3 mat3
#define float4x4 mat4
#define Texture2D sampler2D
#define mul(v, m) (m) * (v)

#define N_PASSES 6

#ifndef TONEMAP_OPERATOR
#define TONEMAP_OPERATOR TONEMAP_FILMIC
#endif

#define TONEMAP_LINEAR 0
#define TONEMAP_EXPONENTIAL 1
#define TONEMAP_EXPONENTIAL_HSV 2
#define TONEMAP_REINHARD 3
#define TONEMAP_FILMIC 4

uniform float exposure;
//uniform float burnout;
//uniform float bloomWidth;
uniform float bloomIntensity;
//uniform float bloomThreshold;
uniform float defocus;

uniform float2 pixelSize;
uniform float2 direction;

uniform sampler2D finalTex;
uniform sampler2D srcTex[N_PASSES];

float3 FilmicTonemap(float3 x) {
    float A = 0.15;
    float B = 0.50;
    float C = 0.10;
    float D = 0.20;
    float E = 0.02;
    float F = 0.30;
    float W = 11.2;
    return ((x*(A*x+C*B)+D*E) / (x*(A*x+B)+D*F))- E / F;
}

float3 DoToneMap(float3 color) {
    #if TONEMAP_OPERATOR == TONEMAP_LINEAR
    return exposure * color;
    #elif TONEMAP_OPERATOR == TONEMAP_EXPONENTIAL
    color = 1.0 - exp2(-exposure * color);
    return color;
    #elif TONEMAP_OPERATOR == TONEMAP_EXPONENTIAL_HSV
    color = rgb2hsv(color);
    color.b = 1.0 - exp2(-exposure * color.b);
    color = hsv2rgb(color);
    return color;
    #elif TONEMAP_OPERATOR == TONEMAP_REINHARD
    color = xyz2Yxy(rgb2xyz(color));
    float L = color.r;
    L *= exposure;
    float LL = 1 + L / (burnout * burnout);
    float L_d = L * LL / (1 + L);
    color.r = L_d;
    color = xyz2rgb(Yxy2xyz(color));
    return color;
    #else // TONEMAP_FILMIC
    color = 2.0f * FilmicTonemap(exposure * color);
    float3 whiteScale = 1.0f / FilmicTonemap(vec3(11.2));
    color *= whiteScale;
    return color;
    #endif
}

float4 PyramidFilter(Texture2D tex, float2 uv, float2 width) {
    float4 color = texture(tex, uv + vec2(0.5, 0.5) * width);
    color += texture(tex, uv + vec2(-0.5,  0.5) * width);
    color += texture(tex, uv + vec2( 0.5, -0.5) * width);
    color += texture(tex, uv + vec2(-0.5, -0.5) * width);
    return 0.25 * color;
}

in vec2 uv;
out vec4 out_color;

void process(sampler2D tex, float w)
{
    float4 sample = texture(tex, uv);
    out_color.rgb += bloomIntensity * w * sample.rgb / 127.0;
    //out_color.a += sample.a / N_PASSES;
    out_color.a += sample.a / 6.0;
}

void main()
{
    float w[] = float[] (64.0, 32.0, 16.0, 8.0, 4.0, 2.0, 1.0);

    out_color = PyramidFilter(finalTex, uv, pixelSize * defocus);
//    for (int i = 0; i < N_PASSES; i++)
//    {
//        float4 sample = texture(srcTex[i], uv);
//        out_color.rgb += bloomIntensity * w[i] * sample.rgb / 127.0;
//        out_color.a += sample.a / N_PASSES;
//        process(srcTex[i], w[i]);
//    }
    process(srcTex[0], w[0]);
    process(srcTex[1], w[1]);
    process(srcTex[2], w[2]);
    process(srcTex[3], w[3]);
    process(srcTex[4], w[4]);
    process(srcTex[5], w[5]);

    out_color.rgb = DoToneMap(out_color.rgb);
}